#!/usr/bin/env python3
import json
import re
from urllib.parse import urlparse, parse_qs
from datetime import datetime
import hashlib

class IDEARequestAnalyzer:
    def __init__(self):
        self.idea_domains = [
            'jetbrains.com',
            'plugins.jetbrains.com', 
            'www.jetbrains.com',
            'account.jetbrains.com',
            'data.services.jetbrains.com',
            'download.jetbrains.com',
            'cache-redirector.jetbrains.com',
            'package-search.services.jetbrains.com',
            'search.maven.org',
            'repo1.maven.org',
            'repository.apache.org'
        ]
        
        self.sensitive_patterns = [
            r'token[=:]([^&\s]+)',
            r'api[_-]?key[=:]([^&\s]+)', 
            r'password[=:]([^&\s]+)',
            r'secret[=:]([^&\s]+)',
            r'auth[=:]([^&\s]+)',
            r'session[=:]([^&\s]+)'
        ]
        
        self.idea_request_types = {
            'plugin_search': r'/plugins?/search',
            'plugin_download': r'/plugin/download',
            'license_check': r'/license',
            'update_check': r'/update',
            'telemetry': r'/statistics|/telemetry',
            'authentication': r'/auth|/login',
            'marketplace': r'/marketplace',
            'maven_search': r'/search\?q=',
            'maven_download': r'\.jar$|\.pom$'
        }

    def analyze_request(self, request_data):
        """Analyze a single request and extract relevant information"""
        try:
            lines = request_data.split('\n')
            if not lines:
                return None
            
            method_line = lines[0].strip()
            method, url, protocol = method_line.split(' ', 2)
            
            headers = {}
            for line in lines[1:]:
                if ':' in line and line.strip():
                    key, value = line.split(':', 1)
                    headers[key.strip().lower()] = value.strip()
            
            analysis = {
                'timestamp': datetime.now().isoformat(),
                'method': method,
                'url': url,
                'protocol': protocol,
                'headers': headers,
                'is_idea_related': self.is_idea_related(url, headers),
                'request_type': self.classify_request(url),
                'security_concerns': self.check_security_concerns(request_data),
                'parsed_url': self.parse_url_details(url),
                'user_agent_info': self.analyze_user_agent(headers.get('user-agent', ''))
            }
            
            return analysis
            
        except Exception as e:
            return {'error': f'Analysis failed: {e}', 'raw_data': request_data[:200]}

    def is_idea_related(self, url, headers):
        """Check if request is related to IntelliJ IDEA"""
        # Check URL domains
        parsed_url = urlparse(url)
        domain = parsed_url.netloc.lower()
        
        for idea_domain in self.idea_domains:
            if idea_domain in domain:
                return True
        
        # Check User-Agent
        user_agent = headers.get('user-agent', '').lower()
        idea_indicators = ['intellij', 'idea', 'jetbrains', 'plugin', 'marketplace']
        
        for indicator in idea_indicators:
            if indicator in user_agent:
                return True
        
        return False

    def classify_request(self, url):
        """Classify the type of IDEA request"""
        url_lower = url.lower()
        
        for request_type, pattern in self.idea_request_types.items():
            if re.search(pattern, url_lower):
                return request_type
        
        return 'unknown'

    def check_security_concerns(self, request_data):
        """Check for potential security issues in the request"""
        concerns = []
        
        # Check for sensitive data in URL/headers
        for pattern in self.sensitive_patterns:
            matches = re.findall(pattern, request_data, re.IGNORECASE)
            if matches:
                # Hash the sensitive data for logging
                hashed_values = [hashlib.sha256(match.encode()).hexdigest()[:8] for match in matches]
                concerns.append({
                    'type': 'sensitive_data',
                    'pattern': pattern,
                    'hashed_values': hashed_values
                })
        
        # Check for unencrypted transmission of sensitive data
        if 'http://' in request_data and any(pattern in request_data.lower() for pattern in ['password', 'token', 'key']):
            concerns.append({
                'type': 'unencrypted_sensitive_data',
                'description': 'Sensitive data transmitted over HTTP'
            })
        
        return concerns

    def parse_url_details(self, url):
        """Parse URL and extract detailed information"""
        try:
            parsed = urlparse(url)
            query_params = parse_qs(parsed.query)
            
            return {
                'scheme': parsed.scheme,
                'netloc': parsed.netloc,
                'path': parsed.path,
                'query': parsed.query,
                'params': query_params,
                'fragment': parsed.fragment
            }
        except:
            return {'error': 'URL parsing failed'}

    def analyze_user_agent(self, user_agent):
        """Extract information from User-Agent string"""
        if not user_agent:
            return {}
        
        info = {'raw': user_agent}
        
        # Extract IDEA version
        idea_match = re.search(r'IntelliJ IDEA[/\s]+([\d.]+)', user_agent, re.IGNORECASE)
        if idea_match:
            info['idea_version'] = idea_match.group(1)
        
        # Extract OS information
        os_patterns = {
            'windows': r'Windows NT ([\d.]+)',
            'macos': r'Mac OS X ([\d._]+)',
            'linux': r'Linux'
        }
        
        for os_name, pattern in os_patterns.items():
            match = re.search(pattern, user_agent, re.IGNORECASE)
            if match:
                info['os'] = os_name
                if match.groups():
                    info['os_version'] = match.group(1)
                break
        
        return info

    def generate_traffic_report(self, requests_log):
        """Generate a comprehensive traffic analysis report"""
        if not requests_log:
            return {'error': 'No requests to analyze'}
        
        analyzed_requests = []
        for request in requests_log:
            analysis = self.analyze_request(request.get('raw_request', ''))
            if analysis:
                analyzed_requests.append(analysis)
        
        # Generate summary statistics
        total_requests = len(analyzed_requests)
        idea_requests = [r for r in analyzed_requests if r.get('is_idea_related')]
        
        request_types = {}
        domains = {}
        security_issues = []
        
        for request in analyzed_requests:
            # Count request types
            req_type = request.get('request_type', 'unknown')
            request_types[req_type] = request_types.get(req_type, 0) + 1
            
            # Count domains
            parsed_url = request.get('parsed_url', {})
            domain = parsed_url.get('netloc', 'unknown')
            domains[domain] = domains.get(domain, 0) + 1
            
            # Collect security concerns
            security_issues.extend(request.get('security_concerns', []))
        
        report = {
            'timestamp': datetime.now().isoformat(),
            'summary': {
                'total_requests': total_requests,
                'idea_related_requests': len(idea_requests),
                'idea_percentage': round(len(idea_requests) / total_requests * 100, 2) if total_requests > 0 else 0
            },
            'request_types': dict(sorted(request_types.items(), key=lambda x: x[1], reverse=True)),
            'top_domains': dict(sorted(domains.items(), key=lambda x: x[1], reverse=True)[:10]),
            'security_summary': {
                'total_concerns': len(security_issues),
                'concern_types': list(set(concern.get('type') for concern in security_issues))
            },
            'analyzed_requests': analyzed_requests[-50:]  # Last 50 requests for detailed view
        }
        
        return report

    def filter_idea_requests(self, requests_log):
        """Filter only IDEA-related requests"""
        idea_requests = []
        
        for request in requests_log:
            analysis = self.analyze_request(request.get('raw_request', ''))
            if analysis and analysis.get('is_idea_related'):
                idea_requests.append({
                    'original': request,
                    'analysis': analysis
                })
        
        return idea_requests


if __name__ == '__main__':
    analyzer = IDEARequestAnalyzer()
    
    # Test with sample request
    sample_request = """GET https://plugins.jetbrains.com/api/search/plugins?query=python HTTP/1.1
Host: plugins.jetbrains.com
User-Agent: IntelliJ IDEA/2023.3 (Windows NT 10.0)
Accept: application/json
Authorization: Bearer test-token-123"""
    
    analysis = analyzer.analyze_request(sample_request)
    print("Sample Analysis:")
    print(json.dumps(analysis, indent=2))